﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


using STSdb4.Database;
using System.Linq.Expressions;

namespace AL.DAL.Logs {



    /// <summary>
    /// HH: 日志操作类统一入口
    /// </summary>
    public static class Provider {


        private static XIndex<long, OPLog> _table = null;

        private static readonly string Path = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/");
        private const string SystemFileName = "HH_Log.sys";
        private const string DataFileName = "HH_Log.dat";

        private const string DataTableName = "OperationLog";


        // 防止文件占用
        //private static string _lockStatus = "None";
        private static bool _isWorking = false;

        /// <summary>
        /// HH: 新增一条日志记录
        /// </summary>
        public static long Add(OPLog record) {
            //// 如果再出问题就使用 Lock 锁
            //lock (_lockStatus) {
            //    // 需要执行的代码
            //};

            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;
            
            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);

                // 最大 ID 号
                long max = -1;
                if (_table != null && _table.Any()) {
                    max = _table.Max(o => o.Key);
                } else {
                    max = -1;
                }

                record.LogID = max + 1;
                record.CreateDate = DateTime.Now;

                //long length = table.Count();
                if (_table != null)
                {
                    _table[max + 1] = record;

                    _table.Flush();
                }
                engine.Commit();

                _isWorking = false;
                return record.LogID;
            }
        }

        /// <summary>
        /// HH: 批量新增日志记录
        /// </summary>
        public static void AddBatch(List<OPLog> records) {
            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;

            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);
                long length = _table.Count();

                for (int i = 0; i < records.Count; i++) {
                    // 最大 ID 号
                    long max = -1;
                    if (_table != null && _table.Any()) {
                        max = _table.Max(o => o.Key);
                    } else {
                        max = -1;
                    }

                    records[i].LogID = max + 1;
                    records[i].CreateDate = DateTime.Now;
                    
                    _table[max + 1] = records[i];
                }

                _table.Flush();
                engine.Commit();

                _isWorking = false;
            }
        }


        /// <summary>
        /// HH: 编辑一条日志记录
        /// </summary>
        public static void Mod(OPLog record) {
            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;

            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);

                _table.Replace(record.LogID, record);

                _table.Flush();
                engine.Commit();

                _isWorking = false;
            }
        }


        /// <summary>
        /// HH: 根据主键 ID 删除一条日志记录
        /// </summary>
        public static void Del(long id) {
            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;

            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);
                _table.Delete(id);
                _table.Flush();
                engine.Commit();

                _isWorking = false;
            }
        }


        /// <summary>
        /// HH: 批量新增日志记录
        /// </summary>
        public static void DelBatch(string[] ids) {
            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;

            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);

                for (int i = 0; i < ids.Length; i++) {
                    _table.Delete(Convert.ToInt64(ids[i]));
                }

                _table.Flush();
                engine.Commit();

                _isWorking = false;
            }
        }


        /// <summary>
        /// HH: 根据主键 ID 删除一条日志记录
        /// </summary>
        public static void Clear() {
            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;

            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);
                _table.Clear();
                _table.Flush();
                engine.Commit();

                _isWorking = false;
            }
        }



        /// <summary>
        /// HH: 根据 ID 获取一个日志记录对象
        /// </summary>
        public static OPLog GetByID(long id) {
            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;

            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);

                _isWorking = false;
                return _table.TryGetOrDefault(id, new OPLog());
            }
        }




        ///// <summary>
        ///// HH: 根据 ID 获取一个日志记录对象
        ///// </summary>
        //public static IEnumerable<KeyValuePair<long, OPLog>> GetAll() {
        //    using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
        //        _table = engine.OpenXIndex<long, OPLog>(DataTableName);

        //        var list = _table.OrderByDescending(o => o.Key);

        //        return list;
        //    }
        //}




        

        /// <summary>
        /// HH: 查询获取对象集合
        /// </summary>
        public static List<OPLog> Search(List<Func<KeyValuePair<long, OPLog>, bool>> predicate, int inPageIndex, int inPageSize, out int outPageCount) {
            while (_isWorking == true) {
                System.Threading.Thread.Sleep(100);
            }
            _isWorking = true;

            using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
                _table = engine.OpenXIndex<long, OPLog>(DataTableName);

                outPageCount = 0;

                //var list = _table.Backward().Where(predicate);

                // 多条件模式
                //var list = _table.Backward().Where(o => (int)o.Value.OPType == 1);
                var list = _table.Backward();
                foreach (Func<KeyValuePair<long, OPLog>, bool> p in predicate) {
                    list = list.Where(p);
                }



                if (list != null && list.Count() > 0) {

                    // 分页查询
                    int pageSize = inPageSize;
                    int pageIndex = inPageIndex;
                    outPageCount = list.Count();

                    List<OPLog> r = new List<OPLog> { };

                    long rowID = 1;
                    long minID = (pageIndex - 1) * pageSize + 1;
                    long maxID = minID + pageSize - 1;

                    // 遍历
                    foreach (KeyValuePair<long, OPLog> item in list) {
                        if (rowID >= minID && rowID <= maxID) {
                            r.Add(item.Value);
                        }
                        rowID++;

                        if (rowID == maxID + 1) break;
                    }


                    //var ret = table.Backward().Where(predicate).Skip(pageSize * (pageIndex - 1)).Take(pageSize);

                    //List<OPLog> r = new List<OPLog> { };
                    //foreach (KeyValuePair<long, OPLog> item in ret) {
                    //    r.Add(item.Value);
                    //}

                    _isWorking = false;
                    return r;
                }

                _isWorking = false;
                return null;
            }
        }









        ///// <summary>
        ///// HH: 采用 STSdb FindNext 方式获取连续的多条记录（尚未完全实现，排序分页等）
        ///// </summary>
        ///// <param name="id"> 页面中第一个 ID 或者 最后一个 ID </param>
        ///// <param name="isNext"> 是否查下一页数据（True 下一页， False 上一页） </param>
        //public static List<OPLog> PageList(List<Func<OPLog, bool>> predicate, long id, bool isNext, int inPageSize) {
        //    while (_isWorking == true) {
        //        System.Threading.Thread.Sleep(100);
        //    }
        //    _isWorking = true;

        //    using (var engine = new StorageEngine(Path + SystemFileName, Path + DataFileName)) {
        //        _table = engine.OpenXIndex<long, OPLog>(DataTableName);

        //        var r = new List<OPLog> { };
        //        if (isNext) {
        //            // 下一页
        //            while (inPageSize > 0) {
        //                var t = _table.FindNext(id);
        //                if (t != null && t.HasValue) {
        //                    // 此处可以插入条件判断，如果不符合则不添加直接下一条
        //                    //foreach (Func<KeyValuePair<long, OPLog>, bool> p in predicate) {
        //                    //    list = list.Where(p);
        //                    //}
        //                    r.Add(t.Value.Value);
        //                    inPageSize--;
        //                } else {
        //                    // 没有记录跳出
        //                    inPageSize = 0;
        //                    break;
        //                }

        //            }
        //        } else {
        //            // 上一页
        //            while (inPageSize > 0) {
        //                var t = _table.FindPrev(id);
        //                if (t != null && t.HasValue) {
        //                    // 此处可以插入条件判断，如果不符合则不添加直接下一条
        //                    r.Add(t.Value.Value);
        //                    inPageSize--;
        //                } else {
        //                    // 没有记录跳出
        //                    inPageSize = 0;
        //                    break;
        //                }

        //            }
        //        }

        //        _isWorking = false;
        //        return r;
        //    }
        //}



        ///// <summary>
        ///// HH: 根据 ID 获取一个日志记录对象
        ///// </summary>
        //public static IEnumerable<KeyValuePair<long, OPLog>> Search(Func<KeyValuePair<long, OPLog>, bool> predicate, int inPageSize, int inPageIndex, out int outPageCount) {
        //    using (StorageEngine engine = new StorageEngine(_path + _systemFileName, _path + _dataFileName)) {
        //        table = engine.OpenXIndex<long, OPLog>(_dataTableName);

        //        outPageCount = 0;

        //        var list = table.Backward().Where(predicate);
        //        if (list != null && list.Count() > 0) {

        //            // 分页查询
        //            int pageSize = inPageSize;
        //            int pageIndex = inPageIndex;
        //            outPageCount = list.Count();

        //            var ret = list.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
        //            //foreach (KeyValuePair<long, OPLog> item in ret) {
        //            //    var str = item.Value.LogID.ToString() + " " + item.Value.UserName + " " + item.Value.CreateDate.ToString() + " " + item.Value.Description + " " + item.Value.OPType.ToString() + " " + item.Value.NewData;
        //            //}

        //            //var r = from row in ret
        //            //        select new { LogID = row.Value.LogID, UserName = row.Value.UserName, CreateDate = row.Value.CreateDate, Description = row.Value.Description, OPType = row.Value.OPType, NewData = row.Value.NewData };


        //            return ret;
        //        }

        //        return null;
        //    }
        //}



        //int ss = DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;

        ////// 插入数据
        ////using (StorageEngine engine = new StorageEngine("HH_Log.sys", "HH_Log.dat")) {
        ////    XIndex<long, OPLog> table = engine.OpenXIndex<long, OPLog>("OperationLog");
        ////    for (int i = 0; i < 1000000; i++) {
        ////        OPLog row = null;

        ////        if (i % 234 == 0) {
        ////            row = new OPLog() { LogID = i, CreateDate = DateTime.Now, UserName = "TTT", OPType = OPType.用户登录, Description = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 用户 TTT 执行 用户登录", NewData = "{}" };
        ////        } else {
        ////            row = new OPLog() { LogID = i, CreateDate = DateTime.Now, UserName = "HAVENT", OPType = OPType.用户登录, Description = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 用户 HAVENT 执行 用户登录", NewData = "{}" };
        ////        }


        ////        table[i] = row;
        ////    }

        ////    table.Flush();
        ////    engine.Commit();
        ////}

        //int begin = DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;

        //// 查询数据
        //using (StorageEngine engine = new StorageEngine("HH_Log.sys", "HH_Log.dat")) {
        //    XIndex<long, OPLog> table = engine.OpenXIndex<long, OPLog>("OperationLog");
        //    var list = table.Where(o => o.Value.UserName == "TTT");
        //    if (list != null && list.Count() > 0) {

        //        // 分页查询
        //        int pageSize = 20;
        //        int pageIndex = 2;
        //        var ret = list.Skip(pageSize * (pageIndex - 1)).Take(pageSize);
        //        foreach (KeyValuePair<long, OPLog> item in ret) {
        //            var str = item.Value.LogID.ToString() + " " + item.Value.UserName + " " + item.Value.CreateDate.ToString() + " " + item.Value.Description + " " + item.Value.OPType.ToString() + " " + item.Value.NewData;
        //        }

        //        // 获取最大记录ID
        //        var mm = table.Max(o => o.Key);

        //        int end = DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;

        //        MessageBox.Show("mm:" + mm.ToString() +"\r\n" + list.Count().ToString() + "\r\n" + ss.ToString() + "\r\n" + begin.ToString() + "\r\n" + end.ToString());
        //    }
        //}
        //return;


    }





}
